#! /usr/bin/env python
# -*- coding: utf-8 -*-

import re
import os
import time

import FileHostProtoType


class fjitem(FileHostProtoType.HostItem):
    def __init__(self, name, type, id, link, encrypt_name='', server_name=''): 
        FileHostProtoType.HostItem.__init__(self, name, type, id, link, encrypt_name, server_name)
        
class filejungle(FileHostProtoType.FileHostProcess):
    def __init__(self,user,pwd):
        FileHostProtoType.FileHostProcess.__init__(self)
        self.hostname = "FileJungle"
        self._opener = None
        self._user = user
        self._pwd = pwd
        self.islogin = False
        self._ftppwd = ''
        self._cookieCurl = '%s_%s.cookie' % (self._user, self.hostname)
        self._cookieCurl = os.path.join(os.path.dirname(__file__), self._cookieCurl)
        
    def loginFileHost(self,loginurl,logindata):
        return FileHostProtoType.FileHostProcess.loginFileHost(self, loginurl, logindata)

    def login(self):
        '''
        login to FileJungle
        return opener object which includes cookies
        '''
        self.generateOpener()
        if self.restore_cookiejar():
            return True
	
        self.fherr.write('login to FileJungle %s/%s...'%(self._user,'*'*len(self._pwd)))
        loginData = {'loginFormSubmit' : '', 
                'loginUserName' : self._user, 
                'loginUserPassword' : self._pwd,
                'autoLogin' : 'on'}
        self.loginFileHost("http://filejungle.com/login.php", loginData)
		
        cookie_status = self.check_cookie()
        if not cookie_status:
            self.fherr.write("[%s]User %s Status : not Logined." % (time.ctime(), self._user))
            return False
        self.fherr.write('write cookie file.')
        self._cj.save(self._cookieCurl, ignore_discard=True)
        return True   

    def restore_cookiejar(self):
        '''
        load cookie file, then access website to verify if cookie is avaiable
        '''
        if os.path.isfile(self._cookieCurl):
            self.fherr.write('Restore Local Cookie.')
            try:
                self._cj.load(self._cookieCurl, ignore_discard=True)
            except:
                self.fherr.write('Failed to Restore Local CookieJar.')
            #access website to conferm cookie is avaiable
            return self.check_cookie()
        return False
		
    def check_cookie(self):
        indexpage = self.post_request("http://filejungle.com/dashboard.php")
        #you always see you username at the top of the page, if it logins successfully.
        if self._user not in indexpage:
            self.fherr.write("User %s Status: Not Logined." % self._user)
            self.islogin = False
            return False
        self.fherr.write("User %s Status: Logined." % self._user)
        self.islogin = True
        return True
    
    def check_login(self):
        if self.check_cookie():
            return
        self.fherr.write('cookie unavaiable, reLogin...')
        while not self.login():
            time.sleep(5)
        
    def getFtpPwd(self):
        response = self.post_request("http://filejungle.com/ftp_upload.php")
        reFtpPwd = re.compile('Password:</div>.*?<div class="detailRight">(?P<ftppwd>.*?)</div>', re.I|re.S)
        matchIter = reFtpPwd.finditer(response)
        for mi in matchIter:
            self._ftppwd =  mi.group('ftppwd').strip()
            return True
        return False
    
    def getFileList(self):
        folders = self.getFolderList()
        root = fjitem('root','/root','0','')
        folders.append(root)
        files = []
        self.fherr.write("Listing files...")
        for f in folders:
            files.extend(self.getFilesFromFolder(f))
        files.sort()
        return files
    
    def getFileFromRoot(self):
        root = fjitem('root','/root','0','')
        return self.getFilesFromFolder(root)
    
    def getFilesFromFolder(self, folder):
        files = []
        id  = folder.id
        currentpage = 1
        totalpage = 1
        filePerPage = 5000
        url = "http://filejungle.com/file-manager-expand-folder.php"
        self.fherr.write("Getting files from folder...%s" % folder.type)
        while currentpage <= totalpage:
            self.fherr.write("Getting files from folder...%s page %s" % (folder.type, currentpage))
            data = {'current_page':currentpage,
                    'extra':'filesPanel',
                    'files_per_page':filePerPage,
                    'is_search':'false',
                    'parent_folder_id':folder.id,
                    'sort_field':2,
                    'sort_order':'DESC',
                    'total_folder_count':0
                    }
            response = self.post_request(url, data)
            
            unuseField = ['htmlLinkWithNoFileName', 'forumLinkWithNoFileName', 'downloadLinkWithNoFileName', 'htmlLink2WithNoFileName', 'htmlLink', 'downloadLink', 'htmlLink2', 'uploadFileExtension', 'fileSize', 'forumLink', 'downloadCount', 'fileSizeInView', 'fileCreateDate', 'fileCreateTime']
            restr = '|'.join(['"%s":"[^"]*?"'%f for f in unuseField])
            response = re.sub(restr, '', response)
            response = re.sub(',+', ',', response)
            response = response.replace('{,', '{')
            response = response.replace(',}', '}')
            response = response.replace('\/','/')
            
            messageDict = {}
            try:
                exec('messageDict=' + response)
            except:
                self.fherr.write("Failed to Get File list of Folder %s, Page %s" % (folder.type,currentpage))
                continue
            
            filecounts = int(messageDict.get("folder").get("filesCount"))
            totalpage = filecounts/filePerPage + 1
            
            filesDict = messageDict.get("uploads",[])
            
            for f in filesDict:
                id = f.get("uploadId")
                uNameStr = f.get("uploadFileName")
                name = ''
                exec 'name=u"%s"' % uNameStr
                link = f.get("downloadUrl")
                fsI = fjitem(name,'file',id,link)
                files.append(fsI)
            currentpage += 1
        files.sort()
        return files
    
    def getFolderList(self):   
        self.fherr.write("Getting folder list...") 
        foundFolders = []
        url = "http://filejungle.com/file-manager-expand-folder.php"
        data = {"":1,
                "extra":"folderPanel",
                "is_updated_folder_count":"false"}
        response = self.post_request(url, data)
        messageDict = {}
        try:
            exec('messageDict=' + response)
        except:
            self.fherr.write("Failed to Get Folder list.")
            return foundFolders
        foldersDict = messageDict.get("folder")
        for f in foldersDict:
            id = f.get("folderId")
            name = f.get("folderName")
            link = "http://filejungle.com/list/" + f.get("folderShortenCode")
            #although FileJungle allows user to create subdir, I omit it for lazy -_,-
            fsI = fjitem(name, '/' + name, id, link)
            foundFolders.append(fsI)
        foundFolders.sort()
        return foundFolders
    
    def find(self, filenames=[], filelist = None):
        '''
        open the filelist page according to opener with cookies
        '''
        found = []
        if filelist is None:
            filelist = self.getFileList()        
        filelistlower = [fl.name.lower() for fl in filelist]
        todel = []
        for fl in filenames:
            try:
                index = filelistlower.index(os.path.basename(fl).lower())
                found.append(filelist[index])
                todel.append(fl)
            except:
                continue
        for d in todel:
            filenames.remove(d)
        found.sort()
        return found

    def findFolder(self, folderpath):
        '''
        folderpath should like this : /xxx/yyy/zzz
        '''        
        folders = self.getFolderList()
        for f in folders:
            if folderpath == f.type:
                return f
        return None

    def createFolder(self, newfolder):
        '''
        In fact: A file/folder name can't contain any of the following characters: \/:?*"<>|
        but I don't want to deal with it
        '''
        if re.compile("^[a-zA-z0-9-_]+$").match(newfolder.replace('/','')) == None:
            self.fherr.write("The Folder must be more than 2 symbols long and must consist only of A-Z,0-9,- and _")
            return None
        if newfolder[0] != '/':
            newfolder = '/'+newfolder
        if newfolder[-1] != '/':
            newfolder +='/'
        dirs = newfolder.split('/')[1:-1]
        cf = '/'
        foldertree = []
        for f in dirs:
            if f == "":
                continue
            if len(f) < 2:
                self.fherr.write("The Folder must be more than 2 symbols long and must consist only of A-Z,0-9,- and _")
                return None
            cf += f +'/'
            foldertree.append(cf)
            
        remoteFolders = self.getFolderList()
        remoteFolderNames = [f.type+'/' for f in remoteFolders]
        index = 0
        for i in range(len(foldertree)):
            index = i
            if foldertree[i] in remoteFolderNames:                
                self.fherr.write('Folder %s exists.' % foldertree[i])
                if index == len(foldertree) - 1:
                    return remoteFolders[remoteFolderNames.index(foldertree[index])]
                continue
            else:                
                if i == 0:
                    parentFolder = None
                else:
                    parentFolder = remoteFolders[remoteFolderNames.index(foldertree[i-1])]
                break
        justCreated = None
        for i in range(index,len(foldertree)):
            self.fherr.write("Creating...%s" % foldertree[i])
            justCreated = self.__newFolder(dirs[i], parentFolder)
            if justCreated is None:
                self.fherr.write('Fail to create folder %s' % foldertree[i])
            parentFolder = justCreated
        return justCreated

    def __newFolder(self, newfolder, parentfolder=None):
        '''
        newfolder : without any '/',just a standard folder name
        '''
        data =[]
        pid = ''
        parentpath = ''
        if parentfolder is not None:
            pid = parentfolder.id
            parentpath = parentfolder.type
        data.append(('createFolderFormSubmit', 'Create folder'))
        data.append(('folderId', ''))
        data.append(('newFolderName', newfolder))
        data.append(('createFolderDest', pid))
        encodedData = data
        url = "http://filejungle.com/file-manager-action.php"
        response = self.post_request(url, encodedData)     
        self.fherr.write('Message from FileJungle:')
        self.fherr.write(response)
        newfolderPath = '/'.join((parentpath, newfolder))
        if '"success":true' in response:
            for i in range(10):
                time.sleep(10)
                newCreated = self.findFolder(newfolderPath)
                if newCreated is not None:
                    return newCreated
        return self.findFolder(newfolderPath)
    
    def moveto(self, items, destFolder):
        if len(items) == 0:
            return
        data ={}
        data['CurrentFolderId'] = 0
        data['moveFolderDest'] = destFolder.id           
        data['moveFolderId'] = ",".join([i.id for i in items])
        url = "http://filejungle.com/file-manager-action.php"
        response = self.post_request(url, data)        
        self.fherr.write(response)
    
    def upload_web(self, file, progressLog=None, other_args=None):
        return self.upload_to_ftp(file, progressLog, other_args)
       
    def upload_to_ftp(self, file, progressLog=None, other_args=None):
        #make sure cookie is avaible, otherwise we can't get any filelist.
        self.check_login()
        if not self.getFtpPwd():
            self.fherr.write('Fail to get ftp password.')
            return
        
        url = 'ftp://ftp.filejungle.com' 
        userpwd = ('%s:%s' % (self._user, self._ftppwd)).encode('utf8')
        target_name = self.rename_func(file)
        callback = None
        if progressLog is not None:
            callback = progressLog.write
            
        self.fherr.write("Uploading...%s" % file)
        self.upload_file_to_ftp(url, userpwd, file, \
                                target=target_name.encode('utf8'), \
                                callback=callback)
        
        #find new upload file:
        #make sure cookie is avaible, otherwise we can't get any filelist.
        self.check_login()
        time.sleep(30)
        times = self.wait_time/60 + 1
        while times > 0:
            root = self.createFolder('Ftp')
            rootfiles = self.getFilesFromFolder(root)
            find_result = self.find([target_name,], rootfiles)
            if find_result:
                new_file = find_result[0]     
                item = fjitem(os.path.basename(file), \
                              'file', \
                              new_file.id, \
                              new_file.link, \
                              target_name,\
                              new_file.server_name)
                self.newupload.append(item)
                return item
            times -= 1
            time.sleep(60)

if __name__ == "__main__":
    pass
